package Netty.common;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

import java.io.ByteArrayOutputStream;

public class Server {
    public static void main(String[] args) throws Exception {
        //处理连接请求的线程组
        EventLoopGroup bossGroup = new NioEventLoopGroup(2);
        //处理客户端业务的线程组
        EventLoopGroup workerGroup = new NioEventLoopGroup(10);
        try {
            //创建服务器端的启动对象
            ServerBootstrap bootstrap = new ServerBootstrap();
            //设置两个线程组
            bootstrap.group(bossGroup, workerGroup)
                    //使用NioServerSocketChannel作为服务器的通道实现
                    .channel(NioServerSocketChannel.class)
                    // 创建通道初始化对象，设置初始化参数
                    .childHandler(new Server().new MyServerChannelInitializer())
                    // 初始化服务器连接队列大小，服务端将不能处理的客户端连接请求放在队列中等待处理
                    .option(ChannelOption.SO_BACKLOG, 1024);
            //启动服务器，bind是异步操作，sync方法是等待异步操作执行完毕
            ChannelFuture channelFuture = bootstrap.bind(8080).sync();
            System.out.println("Server started");
            // 对通道关闭进行监听，closeFuture是异步操作，通过sync方法同步等待通道关闭处理完毕
            channelFuture.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    /**
     * ChannelInitializer
     */
    class MyServerChannelInitializer extends ChannelInitializer<SocketChannel> {
        protected void initChannel(SocketChannel socketChannel) throws Exception {
            System.out.println("----- init ChannelPipeline：" + Thread.currentThread().getName());
            socketChannel.pipeline().addLast(new MyChannelHandler());
        }
    }

    /**
     * 处理入站事间
     */
    class MyChannelHandler extends ChannelInboundHandlerAdapter {
        //读取客户端发送的数据
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            System.out.println("----- channelRead：" + Thread.currentThread().getName());
            //将 msg 转成一个 ByteBuf，类似NIO 的 ByteBuffer
            ByteBuf buf = (ByteBuf) msg;
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            while (buf.readableBytes() > 0) {
                baos.write(buf.readByte());
            }
            System.out.println("客户端发来消息:" + new String(baos.toByteArray()));
        }
        //数据读取完毕处理方法
        @Override
        public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
            System.out.println("----- channelReadComplete：" + Thread.currentThread().getName());
            ByteBuf buf = Unpooled.copiedBuffer("消息已读\n".getBytes());
            ctx.writeAndFlush(buf);
        }
        //处理异常
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            System.out.println("----- exceptionCaught：" + Thread.currentThread().getName());
            cause.printStackTrace();
            ctx.close();
        }
    }
}